/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package phd.dupenois.changeidentifiers.shapedifferences;

import java.awt.Shape;
import java.awt.geom.Area;
import java.awt.geom.GeneralPath;
import java.awt.geom.PathIterator;
import phd.dupenois.changeidentifiers.footprints.Footprint;
import phd.dupenois.changeidentifiers.shapedifferences.frames.MainFrame;
import uk.co.dupenois.geometry.Coordinate;

/**
 *
 * @author mpd209
 */
public class SymmetricAreaDifference implements ShapeDifferenceMeasure{
    private MainFrame frame;
    public SymmetricAreaDifference(MainFrame frame){
        this.frame = frame;
    }
    public SymmetricAreaDifference(){
    }
    public double getDifference(Footprint wantedFootprint, Footprint actualFootprint) {
        double scalingArea = wantedFootprint.getArea();
        GeneralPath gp1 = actualFootprint.constructGeneralPath();
//        if(frame!=null)frame.setGeneralPath1(gp1);
        GeneralPath gp2 = wantedFootprint.constructGeneralPath();
//        if(frame!=null)frame.setGeneralPath2(gp2);
        Area area1 = new Area(gp1);
        Area area2 = new Area(gp2);

        //Make area1 is the union of area 1 and 2 minus the intersection.
        //Thus it is all the area not in both
        area1.exclusiveOr(area2);
        if(frame!=null)frame.setArea(area1);

        //Get area of area
//        return SymmetricAreaDifference.getArea(area1);
        Footprint footprintOfArea = areaToFootprint(area1);
        double areaDiff = (footprintOfArea.getArea()/scalingArea)*100d;
//        System.out.println("Symmetric Area Diff: "+areaDiff);
        return Math.abs(areaDiff);
    }

    public Footprint areaToFootprint(Area area){
        PathIterator pit = area.getPathIterator(null,.00001);
        Footprint footprint = new Footprint();
        Coordinate currentLocation = null;
        Coordinate previousLocation = null;
        Coordinate movedToLocation = null;
        double[] seg = new double[6];
        
        while (!pit.isDone()) {
            int retVal = pit.currentSegment(seg);

            if(retVal == PathIterator.SEG_MOVETO) {
                currentLocation = new Coordinate(seg[0], seg[1]);
                movedToLocation = currentLocation;
            }else if (retVal == PathIterator.SEG_LINETO) {
                currentLocation = new Coordinate(seg[0], seg[1]);
//                System.out.println("Adding "+previousLocation.toString()+" to "+currentLocation.toString());
                if(previousLocation!=null&&!previousLocation.equals(currentLocation))
                    footprint.addLine(previousLocation, currentLocation);
            }else { //SEG_CLOSE
                currentLocation = movedToLocation;
                if(previousLocation!=null&&!previousLocation.equals(currentLocation))
                    footprint.addLine(previousLocation, currentLocation);
            }
            previousLocation = currentLocation;
            pit.next();
        }
        return footprint;
    }

    /*
     * What this does is turn the shape into a very close polygonal approximation.
     It then uses the Surveyor's Formula to find the area of the polygonal
     approximation.
     */
    public static double getArea(Shape r) {
        PathIterator pit = r.getPathIterator(null,.00001);

        double totalAreaX2 = 0;
        double areaTmp = 0;

        double[] seg = new double[6];
            //[0] = current x
            //[1] = current y
            //[2] = previous x
            //[3] = previous y
            //[4] = last moveTo x
            //[5] = last moveTo y


        while (!pit.isDone()) {
            int retVal = pit.currentSegment(seg);

            if(retVal == PathIterator.SEG_MOVETO) {
                seg[4] = seg[0];
                seg[5] = seg[1];
            }else if (retVal == PathIterator.SEG_LINETO) {
                areaTmp += (seg[2]*seg[1])-(seg[0]*seg[3]);
            }else { //SEG_CLOSE
                areaTmp += (seg[2]*seg[5])-(seg[4]*seg[3]);

                totalAreaX2 += Math.abs(areaTmp);
                areaTmp = 0;
            }

            seg[2] = seg[0];
            seg[3] = seg[1];
            pit.next();
        }

        return totalAreaX2/2;
    }


    
}
